/**
* @file object_pool.h
* @brief 基于数组的对象池
*/
#ifndef TIANYU_COMMON_OBJECT_POOL_H_
#define TIANYU_COMMON_OBJECT_POOL_H_

#include <string.h>
#include "list_link.h"
#include "object.h"


namespace common
{

	typedef bool( *ObjFunc )( CObj& obj, void* parame );

	class CPoolInterface
	{
	 public:
		virtual ~CPoolInterface( ) { }
		virtual bool Initialize( int32_t capacity ) = 0;
		virtual bool Finalize( ) = 0;
		virtual int32_t size( ) const = 0;
		virtual int32_t capacity( ) const = 0;
		virtual CObj* CreateObject( ) = 0;
		virtual CObj* GetObject4ID( OBJ_ID_TYPE ) = 0;
		virtual bool DestoryObject( OBJ_ID_TYPE ) = 0;
		virtual void LoopFunc( ObjFunc func, void* param ) = 0;
	};

	template< typename T, uint8_t obj_type >
	class CObjectPool : public CPoolInterface
	{
	 public:
		class CObjectNode
		{
		 public:
			CObjectNode( ) : link_( this )
			{
				memset( value_, sizeof( T ), 0 );	
				actived_ = false;
			}
			CListLink< CObjectNode >& link( ) { return link_; }
			T& value( ) { return *( T* )( void* )( &value_ ); }
			bool actived( ) const { return actived_; }
			void set_actived( bool actived ) { actived_ = actived; }
		 private:
			uint8_t value_[ sizeof( T ) ];
			CListLink< CObjectNode > link_; 
			bool actived_;
		};

		CObjectPool( )
		{
			nodes_ = NULL;
			capacity_ = 0;
			size_ = 0;
		}

		virtual bool Initialize( int32_t capacity )
		{
			if( capacity <= 0 )
			{
				return false;
			}
			capacity_ = capacity;
			nodes_ = new CObjectNode[ capacity_ ];
			//构建空闲列表
			nodes_[ 0 ].link( ).LinkAfter( free_head_ );
			for( int32_t i = 0; i < capacity_ - 1; ++i )
			{
				nodes_[ i +1 ].link( ).LinkAfter( nodes_[ i ].link( ) ); 	
			}
			free_tail_.LinkAfter( nodes_[ capacity_ - 1 ].link( ) );
			size_ = 0;
			return true;
		}

		virtual bool Finalize( )
		{
			for( CListLink< CObjectNode >* node = active_head_.next_node( ); node != NULL; node = node->next_node( ) )
			{
				CObjectNode* parent = node->parent();
				if( NULL == parent )
				{
					continue;
				}
                T& t = parent->value( );
                t.~T( );//析构;
			}
			free_head_.Unlink( );
			free_tail_.Unlink( );
			active_head_.Unlink( );
			delete[] nodes_;
			nodes_ = NULL;
			capacity_ = 0;
			size_ = 0;
			return false;
		}

		virtual CObj* CreateObject( )
		{
			if( size_ == capacity_ )
			{
				return NULL;
			}
			CListLink< CObjectNode >* node = free_head_.next_node( );
			if( node == NULL )
			{
				//不应该出现;
				return NULL;
			}
			node->Unlink( );//从空闲链表中取出
			CObjectNode* parent = node->parent( );
			if( NULL == parent )
			{
				//不应该出现
				return NULL;
			}
			T& t = parent->value( );
			new ( &t ) T( );//构造
			a = (obj_type << 24);
			b = parent - nodes_;
			c = a + b;
			t.set_id( ( obj_type << 24 ) + ( parent - nodes_  ) );
			node->LinkAfter( active_head_ );//将节点加入active链表
			parent->set_actived( true );
			size_++;
			return &t;
		}

		virtual bool DestoryObject( OBJ_ID_TYPE id )
		{
			if( ( id >> 24 ) != obj_type )
			{
				return false;
			}
			int32_t index = ( id & 0x00FFFFFF );
			if( index < 0 || index >= capacity_ )
			{
				return false;
			}
			CObjectNode& node = nodes_[ index ];
			if( node.actived( ) == false )
			{
				//瞎tm删
				return false;
			}
			node.link( ).Unlink( );
			T& t = node.value( );
			t.~T( );//析构;
			node.link( ).LinkBefore( free_tail_ );//插入空闲列表;
			node.set_actived( false );
			size_--;
			return true;
		}

		virtual CObj* GetObject4ID( OBJ_ID_TYPE id )
		{
			if( ( id >> 24 ) != obj_type )
			{
				return NULL;
			}
			int32_t index = ( id & 0x00FFFFFF );
			if( index < 0 || index >= capacity_ )
			{
				return NULL;
			}
			CObjectNode& node = nodes_[ index ];
			if( node.actived( ) == false )
			{
				return NULL;
			}
			return &( node.value( ) );
		}

		virtual void LoopFunc( ObjFunc func, void* param )
		{
			for( CListLink< CObjectNode >* node = active_head_.next_node( ); node != NULL; node = node->next_node( ) )
			{
				CObjectNode* parent = node->parent( ); 
				if( NULL == parent )
				{
					continue;
				}
				func( parent->value( ), param );
			}
		}

		virtual int32_t capacity( ) const { return capacity_; }
		virtual int32_t size( ) const { return size_; }

	 private:
		CListLink< CObjectNode > free_head_;
		CListLink< CObjectNode > free_tail_;
		CListLink< CObjectNode > active_head_;
		CObjectNode* nodes_;
		int32_t capacity_;
		int32_t size_; 
		int32_t a;
		int32_t b;
		int32_t c;
	};
};


#endif

